import * as lv from '../../../lvgl'



// class 
export class LvglEditor extends lv.CleanObj {

    helper = new Helper(this)

    constructor(disp:lv.Disp, private childrenWalker: (cb:(child:lv.Obj)=>void)=>void) {
        super(null)

        let drv = disp.driver()
        this.setWidth(drv.horRes())
        this.setHeight(drv.verRes())

        disp.setSysLayer(this)

        let indevData = (disp.driver() as lv.CanvasDispDrv).indevData
        this.on("pressed",()=>{

            let x = indevData?.x()
            let y = indevData?.y()

            let pos = new lv.Point()
            pos.setX(x)
            pos.setY(y)

            try{
                childrenWalker(obj=>{
                    if(obj.hitTest(pos)) {
                        throw obj
                    }
                })

                this.helper.disattach()
                this.emit("active-changed", null)
                
            }catch(e) {
                // bingo
                if(e instanceof lv.Obj) {
                    this.setActive(e)
                }
                else {
                    throw e
                }
            }

            pos.free()
        })

        this.hide()
    }

    public enable() {
        this.helper.disattach()
        this.show()

        let disp = this.disp()
        if(disp.sharedKeyboard) {
            let txtarea = disp.sharedKeyboard.textarea()
            txtarea.clearState("focused")

            disp.sharedKeyboard.hide()
        }
    }
    public disable() {
        this.helper.disattach()
        this.hide()
    }

    setActive(widget:lv.Obj|null) {
        if(widget) {
            if(this.helper.target!==widget) {
                this.helper.disattach()
                this.helper.attach(widget)
                this.emit("active-changed", widget)
            }
        }
        else {
            this.helper.disattach()
        }
    }
}

const handleSize = 10

class HelperHandler extends lv.CleanObj{
    
    constructor(helper: Helper, dirx:number, diry:number) {
        super(helper)
        this.fromJson({
            width: handleSize ,
            height: handleSize ,
            style: {
                "border-width": 1 ,
                "border-color": lv.palette("grey",1) ,
                "border-opa": 180 ,
            }
        })
        let lx=0 , ly=0
        this.draggable(
            ()=>{
                if(!helper.target)
                    return false
                let [x,y] = this.coords()
                lx=x; ly=y;
            } ,
            (pos)=>{
                if(!helper.target)
                    return false
                if(pos.x==lx && pos.y==ly) {
                    return
                }
                if(dirx) {
                    if(dirx<0) {
                        helper.setCoordX(pos.x as number)
                    }
                    let dx = (pos.x as number)-lx
                    let w = helper.width() + dx*dirx
                    helper.setWidth(w)

                    lx = pos.x as number
                }
                else {
                    pos.x = false
                }

                if(diry) {
                    if(diry<0) {
                        helper.setCoordY(pos.y as number)
                    }
                    let dy = (pos.y as number)-ly
                    let h = helper.height() + dy*diry
                    helper.setHeight(h)

                    ly = pos.y as number
                }
                else {
                    pos.y = false
                }

                helper.updateLayout()
                helper.target.updateLayout()
            }
        )
    }
}


class Helper extends lv.CleanObj{

    target: lv.Obj|null = null
    shadow?: lv.CleanObj
    dragger?: lv.Draggable

    private following: ()=>void

    constructor(parent:lv.Obj|null) {
        super(parent)
        ;(window as any).helper = this

        this.clearFlag("clickable")

        this.fromJson({
            visible : false ,
            style: {} ,
            children: [
                {
                    class: HelperHandler ,
                    ref: "lfttop" ,
                    align: "top-left" ,
                    args: [-1, -1]
                } ,
                {
                    class: HelperHandler ,
                    ref: "top" ,
                    align: "top-mid" ,
                    args: [0, -1]
                } ,
                {
                    class: HelperHandler ,
                    ref: "rgttop" ,
                    align: "top-right" ,
                    args: [1, -1]
                } ,
                {
                    class: HelperHandler ,
                    ref: "lft" ,
                    align: "left-mid" ,
                    args: [-1, 0]
                } ,
                {
                    class: HelperHandler ,
                    ref: "rgt" ,
                    align: "right-mid" ,
                    args: [1, 0]
                } ,
                {
                    class: HelperHandler ,
                    ref: "lftbtm" ,
                    align: "bottom-left" ,
                    args: [-1, 1]
                } ,
                {
                    class: HelperHandler ,
                    ref: "btm" ,
                    align: "bottom-mid" ,
                    args: [0, 1]
                } ,
                {
                    class: HelperHandler ,
                    ref: "rgtbtm" ,
                    align: "bottom-right" ,
                    args: [1, 1]
                } ,
                {
                    class: lv.CleanObj ,
                    ref: "shadow"
                }
            ]
        }, this)

        // this.addStyle(Helper.styleActive, 0)
        if(this.shadow) {
            this.shadow.addFlag("event-bubble")
            this.shadow.addStyle(Helper.styleActive, 0)
            this.shadow.setX(handleSize)
            this.shadow.setY(handleSize)
        }

        this.dragger = this.draggable()

        this.following = () => {
            if(!this.target) {
                return
            }
            let w = this.target.width()
            let h = this.target.height()
            super.setWidth(w+2*handleSize)
            super.setHeight(h+2*handleSize)
            let [x,y] = this.target.coords()
            this.setCoords(x-handleSize, y-handleSize)
    
            this.shadow?.setWidth(w)
            this.shadow?.setHeight(h)
        }
    }

    attach(widget:lv.Obj) {

        this.target = widget
        this.following()

        this.show()

        // widget.on("size-changed", this.following)
        // widget.on("style-changed", this.following)
    }

    disattach() {
        
        // this.target?.off("size-changed", this.following)
        // this.target?.off("style-changed", this.following)
        
        this.target = null
        this.hide()
    }

    update() {
        this.following()
    }

    setWidth(w:number) {
        super.setWidth(w)
        w-= 2*handleSize
        this.shadow?.setWidth(w)
        if(this.target) {
            this.target.setWidth(w)
            this.target.emit("rect-changed-by-editor", "width", w)
        }
    }
    setHeight(h:number) {
        super.setHeight(h)
        h-= 2*handleSize
        this.shadow?.setHeight(h)
        if(this.target) {
            this.target.setHeight(h)
            this.target.emit("rect-changed-by-editor", "height", h)
        }
    }
    
    setCoordX(x:number) {
        super.setCoordX(x)
        if(this.target) {
            x+= handleSize
            this.target.setCoordX(x)
            this.target.emit("rect-changed-by-editor", "x", x)
        }
    }
    setCoordY(y:number) {
        super.setCoordY(y)
        if(this.target) {
            y+= handleSize
            this.target.setCoordY(y)
            this.target.emit("rect-changed-by-editor", "y", y)
        }
    }
    
    static styleActive = new lv.Style({
        "border-width": 1 ,
        "border-color": lv.palette("yellow",1) ,
        "border-opa": 100 ,
        "shadow-color": lv.palette("yellow",1) ,
        "shadow-spread": 1 ,
        "shadow-width": 1 ,
    })
}


